#include "EventsHandler.h"
#include <time.h>
#include <iostream>
//#include "DeallocateWrite.h"
#include "NewIO.h"
#include "ComponentsHolder.h"
#include "ParserEvent.h"
#include "EndIO.h"
//#include "StatisticsEvent.h"

using namespace std;

EventsHandler::EventsHandler(void): _stopSimulation(false), _time(0)
{
	_heapEvents = new BinaryMinHeap();
}


EventsHandler::~EventsHandler(void)
{
	delete _heapEvents;
}

void EventsHandler::initSimulation()
{
	//Event * e = new DeallocateWrite(DeallocateTime, 0);
	//addEvent(e);
	//Storage* storage = ComponentsHolder::getInstance()->getStorage();
	Parser* parser = ComponentsHolder::getInstance()->getParser();


	//parser->readPriorityGroups();
	parser->readIOs();
	//storage->clearPlacements();
	
	Event * e = new ParserEvent(SimulationParameters::SimulationTime);
	addEvent(e);
	//e = new StatisticsEvent(50,50);
	//addEvent(e);
}
bool EventsHandler::startSimulation()
{
	clock_t start = clock();
	clock_t total = start;
	int t = 0;
	while (!stopSimulation() && !_heapEvents->isEmpty()){ 
		Event* curEvent = getNextEvent();
		
		if (curEvent->getActionTime() < _time)
		{
			cout.precision(9);
			cout << "Invalid Time!!! (Fashla) \n";
			cout << "Event time: " << curEvent->getActionTime() <<endl;
			cout << " CurrentTime: " << _time << endl;
			
			throw "Invalid Time!!! (Fashla)";
		}
		setTime(curEvent->getActionTime());
		if (_time > t)
		{
			cout << "time is: " << t << endl;
			t+= 1000;
			//ComponentsHolder::getInstance()->getCache()->printCacheState(t);
		}
	
		curEvent->doAction();
		delete curEvent;

	}
	while(!_heapEvents->isEmpty())
	{
		Event* e = getNextEvent();
		ExtentIO* io = e->getData();
		delete e;
		if (io)
			delete io;
	}
	//ComponentsHolder::getInstance()->getStatisticsHandler()->printStatistics();
	cout << "Total time is: " <<  clock() - total << endl;
	return true;
}

double EventsHandler::getTime() const
{
	return _time;
}

void EventsHandler::addEvent( Event* e )
{
	_heapEvents->addEvent(e);
}

bool EventsHandler::stopSimulation()
{
	return _stopSimulation;
}
void EventsHandler::setStopSimulation()
{
	_stopSimulation = true;
}


bool EventsHandler::setTime( double time )
{
	 if (time < _time)
	 	 return false;
	 _time = time;
	 return true;
}
Event* EventsHandler::getNextEvent() 
{
	return _heapEvents->pop();
}
